package com.nomito.minimito.netty;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.nomito.minimito.common.constant.MsgActionEnum;
import com.nomito.minimito.entity.ImGroupfriendEntity;
import com.nomito.minimito.service.ImGroupfriendService;
import com.nomito.minimito.service.ImMsgService;
import com.nomito.minimito.service.ImUserService;
import com.nomito.minimito.externalUtils.maqueUtils.SpringUtil;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;


import java.util.ArrayList;
import java.util.List;


/**
 * 用于处理消息的handler
 * 由于它的传输数据的载体是frame，这个frame 在netty中，是用于为websocket专门处理文本对象的，frame是消息的载体，此类叫：TextWebSocketFrame
 */
@Component
public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
    //用于记录和管理所有客户端的channel
    public static DefaultChannelGroup users = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);



    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
        //获取客户端所传输的消息
        String content = msg.text();
        //1.获取客户端发来的消息
//        System.out.println("收到的消息："+content);
        DataContent dataContent = JSON.parseObject(content, DataContent.class);
        Integer action = dataContent.getAction();
        Channel channel =  ctx.channel();
        //2、判断消息类型，根据不同的类型处理不同的业务
        if (action == MsgActionEnum.CONNECT.type){
            //2.1 当websocket 第一次open的时候，初始化channel，把用的channel 和 userid 关联起来
            Long senderId = dataContent.getChatMsg().getSenderId();
            UserChanelRel.put(senderId,channel);
            //测试
            for (Channel c: users) {
                System.out.println(c.id().asLongText());
            }
            UserChanelRel.output();

        }else if (action == MsgActionEnum.CHAT.type){
            //2.2 聊天类型的消息，把聊天记录保存到数据库，同时标记消息的签收状态[未签收]
            ChatMsg chatMsg = dataContent.getChatMsg();
            String msgContent = chatMsg.getMsg();
            Long senderId = chatMsg.getSenderId();
            Long receiverId = chatMsg.getReceiverId();
            //保存消息到数据库，并且标记为未签收
//            ImUserService userService = (ImUserService) SpringUtil.getBean("imUserService");
//            Long msgId = userService.saveMsg(chatMsg);
//            chatMsg.setMsgId(msgId);

            DataContent dataContentMsg = new DataContent();
            dataContentMsg.setChatMsg(chatMsg);

            //发送消息
            Channel receiverChannel = UserChanelRel.get(receiverId);
            if (receiverChannel==null){
                //离线用户
                ImUserService userService = (ImUserService) SpringUtil.getBean("imUserService");
                Long msgId = userService.saveMsg(chatMsg);
                chatMsg.setMsgId(msgId);

            }else {
                //当receiverChannel不为空时候，从ChannelGroup去查找对应的channel是否存在
                Channel findChannel = users.find(receiverChannel.id());
                if (findChannel != null){
                    //用户在线
                    receiverChannel.writeAndFlush(
                            new TextWebSocketFrame(
                                    JSON.toJSONString(dataContentMsg)
                            )
                    );
                }else {
                    //离线用户
                    ImUserService userService = (ImUserService) SpringUtil.getBean("imUserService");
                    Long msgId = userService.saveMsg(chatMsg);
                    chatMsg.setMsgId(msgId);
                }
            }


        } else if(action == MsgActionEnum.SIGNED.type){
            //2.3 签收消息类型，针对具体的消息进行签收，修改数据库中对应消息的签收状态[已签收]
            ImMsgService msgService = (ImMsgService) SpringUtil.getBean("imMsgService");
            //扩展字段在is_signed类型消息中代表需要去签收的消息id,逗号间隔
            List<Long> extand = dataContent.getExtand();
//            String[] msgsId = msgIdsStr.split(",");
//            List<String> msgIdList = new ArrayList<>();
//            for(Long mid : extand){
//                if (!StringUtils.isEmpty(mid)){
//                    msgIdList.add(mid);
//                }
//            }
//            System.out.println(msgIdList.toString());
            if (extand!=null && !extand.isEmpty() && extand.size()>0){
                //批量签收
                msgService.updateMsgSigned(extand);
            }


        }else if(action == MsgActionEnum.KEEPALIVE.type){
            //2.4 心跳类型的消息
            System.out.println("收到来自channel 为【"+channel+"】的心跳包");
        }
        else if(action == MsgActionEnum.GROUPMSG.type){


            //2.5 群聊走这里 聊天类型的消息，把聊天记录保存到数据库，


            ChatMsg chatMsg = dataContent.getChatMsg();
            String msgContent = chatMsg.getMsg();
            Long senderId = chatMsg.getSenderId();
            Long GroupId = chatMsg.getReceiverId();
            //保存消息到数据库，并且标记为未签收
            ImGroupfriendService groupfriendService = (ImGroupfriendService) SpringUtil.getBean("imGroupfriendService");
            List<Long> groupFriendsId = groupfriendService.listGroupFriendsId(GroupId);
            DataContent dataContentMsg = new DataContent();


//            for (int i = 0; i < groupFriendsId.size(); i++) {
//                Channel receiverChannel = UserChanelRel.get(groupFriendsId.get(i));
//                if (receiverChannel!=null){
//                    Channel findChannel = users.find(receiverChannel.id());
//                    if (findChannel != null){
//                        usersizes++;
//                        onlineUserIds.add(groupFriendsId.get(i));
//                    }else continue;
//                }continue;
//            }

            Integer usersizes = 0;//记录在线用户数的标志位
            List<Long> onlineUserIds = new ArrayList<>();
            for (Long gfId : groupFriendsId) {
                    Channel receiverChannel = UserChanelRel.get(gfId);
                    //如果该用户不在线
                    if (receiverChannel!=null){
                        usersizes++;
                        onlineUserIds.add(gfId);
                    }else continue;
            }


            Integer finalUsersizes = usersizes;

            groupFriendsId.forEach(gfId->{
                dataContentMsg.setChatMsg(chatMsg);
                //发送消息
                Channel receiverChannel = UserChanelRel.get(gfId);

                if (gfId != senderId) {
                    //发给其他人的消息
                    if (receiverChannel==null){
                        //离线用户
//                        users.writeAndFlush(receiverChannel.remoteAddress() + "下线，当前在线人数：" + users.size() + "\n");
                    }else {
                        //当receiverChannel不为空时候，从ChannelGroup去查找对应的channel是否存在
                        Channel findChannel = users.find(receiverChannel.id());
                        if (findChannel != null){
                            //用户在线
                            receiverChannel.writeAndFlush(
                                    new TextWebSocketFrame(
                                            JSON.toJSONString(dataContentMsg)
                                    )
                            );

//                            receiverChannel.writeAndFlush("当前在线用户共："+finalUsersizes+"分别是："+onlineUserIds);

                        }else {
                            //离线用户
                        }
                    }


                } else {
                    //发给自己的消息   JSON.toJSONString(onlineUserIds)
//                    receiverChannel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString("我：" + msg + "\n")));
                    receiverChannel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(onlineUserIds)));
                }

            });




        }
    }

//    // 只要有客户端Channel与服务端连接成功就会执行这个方法
//    @Override
//    public void channelActive(ChannelHandlerContext ctx) throws Exception {
//        // 获取到当前与服务器连接成功的channel
//        Channel channel = ctx.channel();
//        System.out.println(channel.remoteAddress() + "---上线");
//        users.writeAndFlush(channel.remoteAddress() + "---上线\n");
//        // 将当前channel添加到group中
////        users.add(channel);
//    }
//    // 只要有客户端Channel断开与服务端的连接就会执行这个方法
//    @Override
//    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
//        // 获取到当前要断开连接的Channel
//        Channel channel = ctx.channel();
//        System.out.println(channel.remoteAddress() + "------下线");
//        users.writeAndFlush(channel.remoteAddress() + "下线，当前在线人数：" + users.size() + "\n");
//    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        users.add(ctx.channel());
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        String chanelId = ctx.channel().id().asShortText();
        System.out.println("客户端被移除：channel id 为："+chanelId);

        users.remove(ctx.channel());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        //发生了异常后关闭连接，同时从channelgroup移除
        ctx.channel().close();
        users.remove(ctx.channel());
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        String chanelId = ctx.channel().id().asShortText();
        System.out.println("客户端下线：channel id 为："+chanelId);

        users.remove(ctx.channel());
    }
}
